package com.rao.gmall.item.comtroller;

import lombok.SneakyThrows;
import org.redisson.api.*;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.UUID;

/**
 * @author nzmxfan
 * @create 2021-08-09-20:39
 */
@RestController
public class LockTestController {

    @Resource
    RedissonClient redissonClient;

    @Resource
    StringRedisTemplate stringRedisTemplate;

    /*
     * 1.分布式锁与本地锁
     *      分布式锁：名字一样则为同一把锁
     *      本地锁：对象一样为同一把锁
     *
     * 2.读写锁（先写后写、先写后读）
     *      写锁：只能同时一个人使用，加锁
     *      读锁：可多个人同时使用
     *
     * 3.信号量
     *      一增一减，如果结果为 0 ，则需要先增后减，否则堵塞
     *
     * 4.闭锁
     *
     */
    // 读写锁
    @SneakyThrows
    @GetMapping("/write")
    public String write() {
        RReadWriteLock write = redissonClient.getReadWriteLock("wrLock");
        RLock wLock = write.writeLock();
        wLock.lock();
        String writeStr = UUID.randomUUID().toString();
        Thread.sleep(10000);
        stringRedisTemplate.opsForValue().set("mymsg", writeStr);
        wLock.unlock();
        return writeStr;
    }

    @GetMapping("/read")
    public String read() {
        RReadWriteLock write = redissonClient.getReadWriteLock("wrLock");
        RLock rLock = write.readLock();
        rLock.lock();
        String readStr = stringRedisTemplate.opsForValue().get("mymsg");
        rLock.unlock();
        return readStr;
    }

    @GetMapping("/count")
    public String tcc(int size){

        RSemaphore whsggdxtcc = redissonClient.getSemaphore("whsggdxtcc");
        whsggdxtcc.addPermits(size);
        return "whsggdxtcc 停车场有 "+size + "  个车位";
    }

    @GetMapping("/in")
    @SneakyThrows
    public String in() {
        RSemaphore count = redissonClient.getSemaphore("whsggdxtcc");
        count.acquire(1); // 从信号量里面减一个
        return "停车成功。。。。。。。。。";
    }

    // 信号量
    @GetMapping("/out")
    @SneakyThrows
    public String out() {
        RSemaphore count = redissonClient.getSemaphore("whsggdxtcc");
        count.release(1); // 向信号量里面加一个
        return "开车出门。。。。。。。。。";
    }

    // 闭锁
    @GetMapping("/baobei")
    @SneakyThrows
    public String baobei(){
        RCountDownLatch qian = redissonClient.getCountDownLatch("qian");
        qian.trySetCount(7); // 需要七块钱

        qian.await(); // 等待钱到位

        return "有钱了。。。。。。";
    }

    @GetMapping("/xintong")
    @SneakyThrows
    public String xintong(){
        RCountDownLatch qian = redissonClient.getCountDownLatch("qian");
        qian.countDown();

        return "又少了一块钱。。。。。。";
    }
}
